package com.hk.commons.util;

import com.hk.commons.propertyeditors.CustomBooleanEditor;
import com.hk.commons.propertyeditors.CustomLocalDateEditor;
import com.hk.commons.propertyeditors.CustomLocalDateTimeEditor;
import com.hk.commons.propertyeditors.CustomLocalTimeEditor;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.PropertyAccessorFactory;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * PropertyAccessor utils
 *
 * @author kevin
 * @date 2018-05-04 13:55
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class PropertyAccessorUtils {

    /**
     * create BeanWrapper by Obj
     *
     * @param obj obj
     * @return BeanWrapper
     */
    public static BeanWrapper forBeanPropertyAccess(Object obj) {
        var beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(obj);
        registryDefaultEditor(beanWrapper);
        return beanWrapper;
    }

    /**
     * create BeanWrapper by clazz
     *
     * @param clazz clazz
     * @return BeanWrapper
     */
    public static BeanWrapper forBeanPropertyAccess(Class<?> clazz) {
        var beanWrapper = new BeanWrapperImpl(clazz);
        registryDefaultEditor(beanWrapper);
        return beanWrapper;
    }

    public static ConfigurablePropertyAccessor forDirectFieldAccess(Object obj) {
        var fieldAccess = PropertyAccessorFactory.forDirectFieldAccess(obj);
        registryDefaultEditor(fieldAccess);
        return fieldAccess;
    }

    private static void registryDefaultEditor(ConfigurablePropertyAccessor propertyAccessor) {
        propertyAccessor.setAutoGrowNestedPaths(true);
        propertyAccessor.setConversionService(ConverterUtils.DEFAULT_CONVERSION_SERVICE);
        propertyAccessor.registerCustomEditor(Boolean.class, CustomBooleanEditor.getAllowEmptyInstance());
        propertyAccessor.registerCustomEditor(LocalDate.class, CustomLocalDateEditor.getInstance());
        propertyAccessor.registerCustomEditor(LocalTime.class, CustomLocalTimeEditor.getInstance());
        propertyAccessor.registerCustomEditor(LocalDateTime.class, CustomLocalDateTimeEditor.getInstance());
    }
}
